package boKe.reflect.spring;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.ConvertUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class XmlApplicationContext {

	private List<BeanDefinition> beanDefines = new ArrayList<BeanDefinition>();
	private Map<String, Object> sigletons = new HashMap<String, Object>();

	public XmlApplicationContext(String fileName) {
		readXmlFile(fileName);
		instanceBeans();
		injectObject();
	}

	public Object getBean(String beanName) {
		return this.sigletons.get(beanName);
	}

	/**
	 * 读取xml
	 * 
	 * @param fileName
	 *            文件名
	 */
	private void readXmlFile(String fileName) {
		SAXReader saxReader = new SAXReader();
		Document doucment = null;
		try {
			doucment = saxReader.read(this.getClass().getResourceAsStream(
					fileName));
		} catch (DocumentException e) {
			e.printStackTrace();
		}

		List<Element> beans = doucment.getRootElement().elements();
		for (Element bean : beans) {
			String id = bean.attributeValue("id");
			String clazz = bean.attributeValue("class");
			BeanDefinition beanDefine = new BeanDefinition(id, clazz);
			List<Element> propertys = bean.elements();
			for (Element property : propertys) {
				String propertyName = property.attributeValue("name");
				String propertyRef = property.attributeValue("ref");
				String propertyValue = property.attributeValue("value");
				PropertyDefinition propertyDefinition = new PropertyDefinition(
						propertyName, propertyRef, propertyValue);
				beanDefine.getPropertys().add(propertyDefinition);
			}

			beanDefines.add(beanDefine);
		}
	}

	/***
	 * 完成实例化对象
	 */
	private void instanceBeans() {
		for (BeanDefinition beanDefinition : beanDefines) {
			if (beanDefinition.getClassName() != null
					&& !"".equals(beanDefinition.getClassName().trim())) {
				try {
					sigletons.put(beanDefinition.getId(),
							Class.forName(beanDefinition.getClassName())
									.newInstance());
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 为bean对象的属性注入值
	 */
	private void injectObject() {
		for (BeanDefinition beanDefinition : beanDefines) {
			Object bean = sigletons.get(beanDefinition.getId());
			if (bean != null) {
				try {
					// 获取当前对象所有的属性
					PropertyDescriptor[] ps = Introspector.getBeanInfo(
							bean.getClass()).getPropertyDescriptors();
					for (PropertyDefinition propertyDefinition : beanDefinition
							.getPropertys()) {
						for (PropertyDescriptor propertyDescriptor : ps) {
							// 用于比较当前在xml文件中配置的属性是否也在获取的对象的属性中
							if (propertyDefinition.getName().equals(
									propertyDescriptor.getName())) {
								Method setter = propertyDescriptor
										.getWriteMethod();// 获取属性的setter方法
								if (setter != null) {
									Object value = null;
									if (propertyDefinition.getRef() != null
											&& !propertyDefinition.getRef()
													.equals("")) {
										value = sigletons
												.get(propertyDefinition
														.getRef());

									} else {
										// 类型的转换将字符串类型转化为基本类型
										value = ConvertUtils.convert(
												propertyDefinition.getValue(),
												propertyDescriptor
														.getPropertyType());
									}
									// 如果setter方法是private
									setter.setAccessible(true);
									setter.invoke(bean, value);
								}
							}
						}
					}

				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}
}
